﻿using System;
using System.Drawing;
using System.Windows.Forms;
using DAPNet;
using ZedGraph;

namespace Benchmark
{
    public partial class ClickCorrectionStatsViewForm : Form
    {
        static private Color DarkPink = Color.FromArgb(129, 0, 81);

        static private Color LightPink = Color.FromArgb(227, 102, 181);

        static private Color DarkOrange = Color.FromArgb(166, 70, 0);

        static private Color LightOrange = Color.FromArgb(255, 174, 115);

        static private Color DarkBlue = Color.FromArgb(0, 103, 92);

        static private Color LightBlue = Color.FromArgb(93, 207, 195);

        static private Color DarkGreen = Color.FromArgb(109, 156, 0);

        static private Color LightGreen = Color.FromArgb(207, 247, 111);


        static private Color DeclickedCurveColor = DarkBlue;

        static private Color SamplesCurveColor = DarkGreen;

        static private Color ClickingCurveColor = DarkPink;

        static private Color ClickedCurveColor = DarkOrange;

        static private Color PerfectDetectionCurveColor = LightBlue;

        static private Color PositiveSliceColor = DarkGreen;

        static private Color NegativeSliceColor = DarkBlue;


        static private string DoubleFormat = "0.000000";

        static private double SliceDisplacement = 0.05;

        static private SymbolType ShownSymbol = SymbolType.Plus;

        static private SymbolType HiddenSymbol = SymbolType.None;


        private ClickCorrectionStats stats;

        private LineItem declickedCurve;

        private LineItem clickedCurve;

        private LineItem samplesCurve;

        private LineItem clickingCurve;

        private LineItem perfectDetectionCurve;

        private PieItem positiveSlice;

        private PieItem negativeSlice;


        public ClickCorrectionStatsViewForm(ClickCorrectionStats statistics)
        {
            InitializeComponent();

            correctionGraph.ScrollDoneEvent += new ZedGraphControl.ScrollDoneHandler(correctionGraph_ScrollDoneEvent);
            correctionGraph.ZoomEvent += new ZedGraphControl.ZoomEventHandler(correctionGraph_ZoomEvent);

            this.stats = statistics;
        }

        private void ClickCorrectionForm_Load(object sender, EventArgs e)
        {
            InicializeStats();
            InicializeDetection();
            InicializeDisplay();

            ResetDisplay(0, stats.Count - 1);
            ResetStats(0, stats.Count - 1);
            ResetCorrection(0, stats.Count - 1);
        }


        private void InicializeDisplay()
        {
            displayDeclickedCheckBox.Checked = true;
            displayClickedCheckBox.Checked = true;
            displaySamplesCheckBox.Checked = true;
            displayClickingCheckBox.Checked = true;
        }

        private void InicializeStats()
        {
            statsGraph.GraphPane.Title.IsVisible = false;
            statsGraph.GraphPane.Legend.IsVisible = false;

            positiveSlice = statsGraph.GraphPane.AddPieSlice(0, PositiveSliceColor, SliceDisplacement, "Positive");
            negativeSlice = statsGraph.GraphPane.AddPieSlice(0, NegativeSliceColor, SliceDisplacement, "Negative");

            statsGraph.GraphPane.AxisChange();
        }

        private void InicializeDetection()
        {
            correctionGraph.GraphPane.Title.IsVisible = false;
            correctionGraph.IsEnableVPan = false;
            correctionGraph.IsEnableVZoom = false;
            correctionGraph.GraphPane.XAxis.Title.Text = "Sample";
            correctionGraph.GraphPane.YAxis.Title.Text = "Ampitude";

            declickedCurve = AddSamplesCurve("Declicked", stats.Declicked, DeclickedCurveColor);
            clickedCurve = AddSamplesCurve("Clicking samples", stats.Clicked, ClickedCurveColor);
            samplesCurve = AddSamplesCurve("Samples", stats.Samples, SamplesCurveColor);
            clickingCurve = AddSamplesCurve("Clicking", stats.Clicking, ClickingCurveColor);
            perfectDetectionCurve = AddDetectionCurve("Perfect detection", stats.PerfectDetection, DAPNet.Sample.MinValue, DAPNet.Sample.BaseValue, PerfectDetectionCurveColor);

            correctionGraph.GraphPane.AxisChange();
        }


        private void ResetDisplay(int startIndex, int endIndex)
        {
            startTextBox.Text = startIndex.ToString();
            endTextBox.Text = endIndex.ToString();

            displayDeclickedSymbolsCheckBox.Enabled = displayDeclickedCheckBox.Checked;
            displaySamplesSymbolsCheckBox.Enabled = displaySamplesCheckBox.Checked;
            displayClickingSymbolsCheckBox.Enabled = displayClickingCheckBox.Checked;
            displayClickedSymbolsCheckBox.Enabled = displayClickedCheckBox.Checked;

            displayGroupBox.Refresh();
        }

        private void ResetStats(int startIndex, int endIndex)
        {
            double avgAbsDifference = stats.GetAvgAbsDifference(startIndex, endIndex);
            averageTextBox.Text = avgAbsDifference.ToString(DoubleFormat);

            double deviationDifferecne = stats.GetDeviationDifference(startIndex, endIndex);
            deviationTextBox.Text = deviationDifferecne.ToString(DoubleFormat);

            double clicksPerfect = stats.PerfectDetection.GetNumClicks(startIndex, endIndex);
            numberTextBox.Text = clicksPerfect.ToString();

            double positivesPerfect = stats.PerfectDetection.GetNumDetections(true, startIndex, endIndex);
            lengthTextBox.Text = (positivesPerfect / clicksPerfect).ToString(DoubleFormat);

            double count = endIndex - startIndex + 1;

            double numPositives = stats.PerfectDetection.GetNumDetections(true, startIndex, endIndex);
            positiveSlice.Value = numPositives / count;

            double numNegatives = stats.PerfectDetection.GetNumDetections(false, startIndex, endIndex);
            negativeSlice.Value = numNegatives / count;

            statisGroupBox.Refresh();
        }

        private void ResetCorrection(int startIndex, int endIndex)
        {
            correctionGraph.GraphPane.XAxis.Scale.Min = startIndex;
            correctionGraph.GraphPane.XAxis.Scale.Max = endIndex;
            correctionGraph.GraphPane.YAxis.Scale.Min = DAPNet.Sample.MinValue;
            correctionGraph.GraphPane.YAxis.Scale.Max = DAPNet.Sample.MaxValue;

            declickedCurve.Symbol.Type = displayDeclickedSymbolsCheckBox.Checked ? ShownSymbol : HiddenSymbol;
            declickedCurve.Color = displayDeclickedCheckBox.Checked ? DeclickedCurveColor : Color.Transparent;
            samplesCurve.Symbol.Type = displaySamplesSymbolsCheckBox.Checked ? ShownSymbol : HiddenSymbol;
            samplesCurve.Color = displaySamplesCheckBox.Checked ? SamplesCurveColor : Color.Transparent;
            clickingCurve.Symbol.Type = displayClickingSymbolsCheckBox.Checked ? ShownSymbol : HiddenSymbol;
            clickingCurve.Color = displayClickingCheckBox.Checked ? ClickingCurveColor : Color.Transparent;
            clickedCurve.Symbol.Type = displayClickedSymbolsCheckBox.Checked ? ShownSymbol : HiddenSymbol;
            clickedCurve.Color = displayClickedCheckBox.Checked ? ClickedCurveColor : Color.Transparent;

            correctionGraph.AxisChange();
            correctionGraph.Refresh();
        }


        private void displayAllButton_Click(object sender, EventArgs e)
        {
            ResetDisplay(0, stats.Count - 1);
            ResetStats(0, stats.Count - 1);
            ResetCorrection(0, stats.Count - 1);
        }

        private void displayButton_Click(object sender, EventArgs e)
        {
            int startIndex = 0;
            bool isStartIndexValid = Int32.TryParse(startTextBox.Text, out startIndex);
            startIndex = Math.Max(0, startIndex);

            int endIndex = 0;
            bool isEndIndexValid = Int32.TryParse(endTextBox.Text, out endIndex);
            endIndex = Math.Min(stats.Count - 1, endIndex);

            if (isStartIndexValid && isEndIndexValid && startIndex < endIndex)
            {
                ResetDisplay(startIndex, endIndex);
                ResetStats(startIndex, endIndex);
                ResetCorrection(startIndex, endIndex);
            }
        }

        private void correctionGraph_ScrollDoneEvent(ZedGraphControl sender, ScrollBar scrollBar, ZoomState oldState, ZoomState newState)
        {
            correctionGraph_ZoomEvent(sender, oldState, newState);
        }

        private void correctionGraph_ZoomEvent(ZedGraphControl sender, ZoomState oldState, ZoomState newState)
        {
            int startIndex = (int)correctionGraph.GraphPane.XAxis.Scale.Min;
            startIndex = Math.Max(0, startIndex);

            int endIndex = (int)correctionGraph.GraphPane.XAxis.Scale.Max;
            endIndex = Math.Min(stats.Count - 1, endIndex);

            ResetDisplay(startIndex, endIndex);
            ResetStats(startIndex, endIndex);
            ResetCorrection(startIndex, endIndex);
        }

        private void displayCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            int startIndex = (int)correctionGraph.GraphPane.XAxis.Scale.Min;
            int endIndex = (int)correctionGraph.GraphPane.XAxis.Scale.Max;
            
            ResetDisplay(startIndex, endIndex);
            ResetCorrection(startIndex, endIndex);
        }


        private LineItem AddSamplesCurve(string label, SampleCollection samples, Color color)
        {
            PointPairList samplePoints = new PointPairList();
            for (int i = 0; i < samples.Count; i++)
            {
                double value = samples[i].Value;
                samplePoints.Add(i, value);
            }

            LineItem samplesCurve = correctionGraph.GraphPane.AddCurve(label, samplePoints, color, SymbolType.None);
            samplesCurve.Line.IsSmooth = true;
            return samplesCurve;
        }

        private LineItem AddDetectionCurve(string label, ClickDetection detection, double positiveValue, double negativeValue, Color color)
        {
            double offset = 0.5;
            PointPairList detectionPoints = new PointPairList();
            for (int i = 0; i < detection.Count; i++)
            {
                double value = detection[i] ? positiveValue : negativeValue;
                detectionPoints.Add(i - offset, value);
            }

            LineItem detectionCurve = correctionGraph.GraphPane.AddCurve(label, detectionPoints, Color.Transparent, SymbolType.None);
            detectionCurve.Line.Fill = new Fill(color);
            detectionCurve.Line.StepType = StepType.ForwardStep;
            return detectionCurve;
        }
    }
}
